package com.tencent.wxcloudrun.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;

import java.util.List;
import java.util.Map;

public class JacksonUtils {


    public static ObjectMapper objectMapper;

    public static String toJSONString(Object object) {
        if (null == objectMapper) {
            objectMapper = new ObjectMapper();
        }

        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            // e.printStackTrace();
            throw new RuntimeException("Resolving Object to json String error: " + e);
        }
    }


    /**
    * json 串转对象 （不带泛型）
    * */
    public static <T> T parseObject(String jsonString, Class<T> valueType) {
        if (null == objectMapper) {
            objectMapper = new ObjectMapper();
        }
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        try {
            return objectMapper.readValue(jsonString, valueType);
        } catch (JsonProcessingException e) {
            // e.printStackTrace();
            throw new RuntimeException("Resolving json String to Object error: " + e);
        }
    }

    /**
     * json 串转对象 （带泛型）
     * 比 Class<T> valueType 的参数更通用了
     * TypeReference<T> valueType 可以接收一个 再嵌套着泛型的类， 例如 Page<T>
     *  例如
     *     TypeReference<HashMap<String, Integer>> hashMapTypeReference = new TypeReference<HashMap<String, Integer>>(){};
     *  例如
     *     TypeReference<Page<BaseDto>> pageTypeReference = new TypeReference<Page<BaseDto>>(){};
     * 而对于Class<T> valueType 显然 不能用Page<BaseDto> 作为参数
     * */
    public static <T> T parseObject(String jsonString, TypeReference<T> valueType) {
        if (null == objectMapper) {
            objectMapper = new ObjectMapper();
        }
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        try {
            return objectMapper.readValue(jsonString, valueType);
        } catch (JsonProcessingException e) {
            // e.printStackTrace();
            throw new RuntimeException("Resolving json String to Object error: " + e);
        }
    }


    /**
     * json 串转 List
     * */
    public static <T> List<T> ofList(String jsonString, Class<T> clazz) {
        if (null == objectMapper) {
            objectMapper = new ObjectMapper();
        }
        CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);
        try {
            return objectMapper.readValue(jsonString, javaType);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Resolving json String to List error: " + e);
        }
    }



    /**
     * json 串转 Map
     * */
    public static <K, V> Map<K, V> ofMap(String jsonString, Class<K> keyClazz, Class<V> valueClazz) {
        if (null == objectMapper) {
            objectMapper = new ObjectMapper();
        }
        MapType javaType = objectMapper.getTypeFactory().constructMapType(Map.class, keyClazz, valueClazz);
        try {
            return objectMapper.readValue(jsonString, javaType);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Resolving json String to Map error: " + e);
        }
    }

}
